Allow examples to be libraries
authorKalita Alexey <kalita.alexey@outlook.com>
Tue, 17 Jan 2017 19:23:48 +0000 (22:23 +0300)
committerKalita Alexey <kalita.alexey@outlook.com>
Tue, 17 Jan 2017 19:23:48 +0000 (22:23 +0300)
src/cargo/core/manifest.rs
src/cargo/core/package.rs
src/cargo/ops/cargo_compile.rs
src/cargo/ops/cargo_rustc/context.rs
src/cargo/ops/cargo_rustc/fingerprint.rs
src/cargo/util/toml.rs

index 86cd6eebd1e57850161806a6d1ae11bd32e5db45..f229281b8d9e54242ad40fb2e1b12dbf4c5f9906 100644 (file)
@@ -104,18 +104,21 @@ pub enum TargetKind {
     Bin,
     Test,
     Bench,
-    Example,
+    ExampleLib(Vec<LibKind>),
+    ExampleBin,
     CustomBuild,
 }
 
 impl Encodable for TargetKind {
     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         match *self {
-            TargetKind::Lib(ref kinds) => {
-                kinds.iter().map(|k| k.crate_type()).collect()
+            TargetKind::Lib(ref kinds) |
+            // TODO: I am not sure whether it should be encoded like a library or like an example
+            TargetKind::ExampleLib(ref kinds) => {
+                kinds.iter().map(LibKind::crate_type).collect()
             }
             TargetKind::Bin => vec!["bin"],
-            TargetKind::Example => vec!["example"],
+            TargetKind::ExampleBin => vec!["example"],
             TargetKind::Test => vec!["test"],
             TargetKind::CustomBuild => vec!["custom-build"],
             TargetKind::Bench => vec!["bench"],
@@ -341,9 +344,17 @@ impl Target {
         }
     }
 
-    pub fn example_target(name: &str, src_path: PathBuf) -> Target {
+    pub fn example_target(name: &str,
+                          crate_targets: Vec<LibKind>,
+                          src_path: PathBuf) -> Target {
+        let kind = if crate_targets.is_empty() {
+            TargetKind::ExampleBin
+        } else {
+            TargetKind::ExampleLib(crate_targets)
+        };
+
         Target {
-            kind: TargetKind::Example,
+            kind: kind,
             name: name.to_string(),
             benched: false,
             ..Target::with_path(src_path)
@@ -415,7 +426,15 @@ impl Target {
     }
 
     pub fn is_bin(&self) -> bool { self.kind == TargetKind::Bin }
-    pub fn is_example(&self) -> bool { self.kind == TargetKind::Example }
+
+    pub fn is_example(&self) -> bool {
+        match self.kind {
+            TargetKind::ExampleBin |
+            TargetKind::ExampleLib(..) => true,
+            _ => false
+        }
+    }
+
     pub fn is_test(&self) -> bool { self.kind == TargetKind::Test }
     pub fn is_bench(&self) -> bool { self.kind == TargetKind::Bench }
     pub fn is_custom_build(&self) -> bool { self.kind == TargetKind::CustomBuild }
@@ -423,13 +442,14 @@ impl Target {
     /// Returns the arguments suitable for `--crate-type` to pass to rustc.
     pub fn rustc_crate_types(&self) -> Vec<&str> {
         match self.kind {
-            TargetKind::Lib(ref kinds) => {
-                kinds.iter().map(|kind| kind.crate_type()).collect()
-            },
+            TargetKind::Lib(ref kinds) |
+            TargetKind::ExampleLib(ref kinds) => {
+                kinds.iter().map(LibKind::crate_type).collect()
+            }
             TargetKind::CustomBuild |
             TargetKind::Bench |
             TargetKind::Test |
-            TargetKind::Example |
+            TargetKind::ExampleBin |
             TargetKind::Bin => vec!["bin"],
         }
     }
@@ -478,7 +498,8 @@ impl fmt::Display for Target {
             TargetKind::Bin => write!(f, "Target(bin: {})", self.name),
             TargetKind::Test => write!(f, "Target(test: {})", self.name),
             TargetKind::Bench => write!(f, "Target(bench: {})", self.name),
-            TargetKind::Example => write!(f, "Target(example: {})", self.name),
+            TargetKind::ExampleBin |
+            TargetKind::ExampleLib(..) => write!(f, "Target(example: {})", self.name),
             TargetKind::CustomBuild => write!(f, "Target(script)"),
         }
     }
index 11e53cf2c9a0a6f393a35a5df833fc7ca28146d0..e3ae1fded5cd7c122fbed99b768af6f9293df63e 100644 (file)
@@ -6,7 +6,7 @@ use std::path::{Path, PathBuf};
 
 use semver::Version;
 
-use core::{Dependency, Manifest, PackageId, SourceId, Target, TargetKind};
+use core::{Dependency, Manifest, PackageId, SourceId, Target};
 use core::{Summary, SourceMap};
 use ops;
 use util::{CargoResult, Config, LazyCell, ChainError, internal, human, lev_distance};
@@ -94,10 +94,10 @@ impl Package {
         self.targets().iter().any(|t| t.is_custom_build())
     }
 
-    pub fn find_closest_target(&self, target: &str, kind: TargetKind) -> Option<&Target> {
+    pub fn find_closest_target(&self, target: &str, is_expected_kind: fn(&Target)-> bool) -> Option<&Target> {
         let targets = self.targets();
 
-        let matches = targets.iter().filter(|t| *t.kind() == kind)
+        let matches = targets.iter().filter(|t| is_expected_kind(t))
                                     .map(|t| (lev_distance(target, t.name()), t))
                                     .filter(|&(d, _)| d < 4);
         matches.min_by_key(|t| t.0).map(|t| t.1)
index 8616774e0ef2467556159f7dfda079b94365216f..870d80a8af7f8bcf963599a1274cad67e4b8cb67 100644 (file)
@@ -295,7 +295,8 @@ impl<'a> CompileFilter<'a> {
                     TargetKind::Bin => bins,
                     TargetKind::Test => tests,
                     TargetKind::Bench => benches,
-                    TargetKind::Example => examples,
+                    TargetKind::ExampleBin |
+                    TargetKind::ExampleLib(..) => examples,
                     TargetKind::Lib(..) => return lib,
                     TargetKind::CustomBuild => return false,
                 };
@@ -374,15 +375,15 @@ fn generate_targets<'a>(pkg: &'a Package,
             }
 
             {
-                let mut find = |names: &[String], desc, kind, profile| {
+                let mut find = |names: &[String], desc, is_expected_kind: fn(&Target) -> bool, profile| {
                     for name in names {
                         let target = pkg.targets().iter().find(|t| {
-                            t.name() == *name && *t.kind() == kind
+                            t.name() == *name && is_expected_kind(t)
                         });
                         let t = match target {
                             Some(t) => t,
                             None => {
-                                let suggestion = pkg.find_closest_target(name, kind);
+                                let suggestion = pkg.find_closest_target(name, is_expected_kind);
                                 match suggestion {
                                     Some(s) => {
                                         let suggested_name = s.name();
@@ -398,10 +399,10 @@ fn generate_targets<'a>(pkg: &'a Package,
                     }
                     Ok(())
                 };
-                find(bins, "bin", TargetKind::Bin, profile)?;
-                find(examples, "example", TargetKind::Example, build)?;
-                find(tests, "test", TargetKind::Test, test)?;
-                find(benches, "bench", TargetKind::Bench, &profiles.bench)?;
+                find(bins, "bin", Target::is_bin, profile)?;
+                find(examples, "example", Target::is_example, build)?;
+                find(tests, "test", Target::is_test, test)?;
+                find(benches, "bench", Target::is_bench, &profiles.bench)?;
             }
             Ok(targets)
         }
index a5a16b4791d672411cf6cfca1945ef58f6bf9583..a46baaa860f8af8559a5032a805440c371532577 100644 (file)
@@ -133,6 +133,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
         for unit in units {
             self.visit_crate_type(unit, &mut crate_types)?;
         }
+        debug!("probe_target_info: crate_types={:?}", crate_types);
         self.probe_target_info_kind(&crate_types, Kind::Target)?;
         if self.requested_target().is_none() {
             self.host_info = self.target_info.clone();
@@ -517,19 +518,22 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
                 };
 
                 match *unit.target.kind() {
-                    TargetKind::Example |
                     TargetKind::Bin |
                     TargetKind::CustomBuild |
+                    TargetKind::ExampleBin |
                     TargetKind::Bench |
                     TargetKind::Test => {
                         add("bin", false)?;
                     }
-                    TargetKind::Lib(..) if unit.profile.test => {
+                    TargetKind::Lib(..) |
+                    TargetKind::ExampleLib(..)
+                    if unit.profile.test => {
                         add("bin", false)?;
                     }
-                    TargetKind::Lib(ref libs) => {
-                        for lib in libs {
-                            add(lib.crate_type(), lib.linkable())?;
+                    TargetKind::ExampleLib(ref kinds) |
+                    TargetKind::Lib(ref kinds) => {
+                        for kind in kinds {
+                            add(kind.crate_type(), kind.linkable())?;
                         }
                     }
                 }
index 3d1f274498f3a443573414f861b53ab7a3c26a1e..02ea5a47f620c31b61484434ab5a500ad5b07eb9 100644 (file)
@@ -657,7 +657,8 @@ fn filename(cx: &mut Context, unit: &Unit) -> String {
         TargetKind::Lib(..) => "lib",
         TargetKind::Bin => "bin",
         TargetKind::Test => "integration-test",
-        TargetKind::Example => "example",
+        TargetKind::ExampleBin |
+        TargetKind::ExampleLib(..) => "example",
         TargetKind::Bench => "bench",
         TargetKind::CustomBuild => "build-script",
     };
index b708d18cf9d09beb018c923e77384d145ea7991b..a46a5a9ad6fa870239196e319e8f1b68a805c57b 100644 (file)
@@ -1159,7 +1159,16 @@ fn normalize(package_root: &Path,
                 PathValue::Path(default(ex))
             });
 
-            let mut target = Target::example_target(&ex.name(), package_root.join(path.to_path()));
+            let crate_types = match ex.crate_type {
+                Some(ref kinds) => kinds.iter().map(|s| LibKind::from_str(s)).collect(),
+                None => Vec::new()
+            };
+
+            let mut target = Target::example_target(
+                &ex.name(),
+                crate_types,
+                package_root.join(path.to_path())
+            );
             configure(ex, &mut target);
             dst.push(target);
         }